﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Xml;
using System.Xml.Linq;
using BloggerAutoPosterService.Engine.Models;
using BloggerAutoPosterService.Engine.Utils;

namespace BloggerAutoPosterService.Engine.Net
{
    public static class RssReader
    {
        private static string getRssAnnotation(this XElement item)
        {
            if (item == null) return string.Empty;
            var annotation = item.Element("{http://www.google.com/schemas/reader/atom/}annotation");
            if (annotation == null) return string.Empty;
            var content = annotation.Element("{http://www.w3.org/2005/Atom}content");
            if (content == null) return string.Empty;
            return content.Value;
        }

        private static string getAtomAnnotation(this SyndicationElementExtensionCollection items)
        {
            if (!items.Any()) return string.Empty;
            var item = items.Where(x => x.OuterName.ToLowerInvariant() == "annotation").FirstOrDefault();
            if (item == null) return string.Empty;

            var element = item.GetObject<XElement>();
            var content = element.Element("{http://www.w3.org/2005/Atom}content");
            if (content == null) return string.Empty;
            return content.Value;
        }

        public static IList<RssEntry> GetEntries(string feedUrl)
        {
            var xnCreator = XName.Get("{http://purl.org/dc/elements/1.1/}creator");

            var feed = XDocument.Load(feedUrl.Trim());
            if (feed.Root == null) return null;

            var channel = feed.Root.Element("channel");
            if (channel == null) return getAtomEntries(feedUrl.Trim());
            var items = channel.Elements("item");

            var feedQuery =
                from item in items
                select new RssEntry
                {
                    Title = item.Element("title").SafeXElementValue().CleanTags(),
                    Description = item.Element("description").SafeXElementValue(),
                    Link = item.Element("link").SafeXElementValue(),
                    PublicationDate = DateTime.Now,
                    Author = item.Element(xnCreator).SafeXElementValue().CleanTags(),
                    BlogName = item.Parent.Element("title").SafeXElementValue(),
                    BlogAddress = item.Parent.Element("link").SafeXElementValue(),
                    Annotation = item.getRssAnnotation().UnescapeXml().CleanTags()
                };

            return feedQuery.ToList();
        }

        private static IList<RssEntry> getAtomEntries(string feedUrl)
        {
            using (var reader = XmlReader.Create(feedUrl.Trim()))
            {
                var feed = SyndicationFeed.Load(reader);
                if (feed == null) throw new NotSupportedException(string.Format("Provided address({0}) is not a valid RSS feed.", feedUrl.Trim()));
                return feed.Items.Select(x =>
                    new RssEntry
                    {
                        Title = x.Title.Text.UnescapeXml().CleanTags(),
                        Author = x.Authors.Any() ? x.Authors.First().Name.UnescapeXml().CleanTags() : string.Empty,
                        Description = x.Content == null ? string.Empty : ((TextSyndicationContent)x.Content).Text.UnescapeXml(),
                        Link = x.Links.Any() ? x.Links.First().Uri.AbsoluteUri : string.Empty,
                        PublicationDate = DateTime.Now,
                        BlogName = x.SourceFeed.Title.Text.UnescapeXml(),
                        BlogAddress = x.SourceFeed.Links.Any() ? x.SourceFeed.Links.First().Uri.AbsoluteUri : string.Empty,
                        Annotation = x.ElementExtensions.getAtomAnnotation().UnescapeXml().CleanTags()
                    }).ToList();
            }
        }
    }
}
